package com.aplink.generic.xmlparser;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import android.content.Context;
import android.content.res.Resources;

import com.aplink.generic.controller.GenericApplication;
import com.aplink.generic.util.ResourcesHelper;

public class XMLPaserUtil {

    private static Document buildDocument(final InputStream istream)
            throws ParserConfigurationException, SAXException, IOException {
        final InputSource isource = new InputSource(new InputStreamReader(
                istream, "UTF-8"));
        final DocumentBuilderFactory dbFactory = DocumentBuilderFactory
                .newInstance();
        final DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
        final Document doc = dBuilder.parse(isource);
        doc.getDocumentElement().normalize();
        return doc;
    }

    public static String getAttrValue(final Node node, final String attrName) {
        final Attr attr = (Attr) node.getAttributes().getNamedItem(attrName);
        if (attr != null) {
            return attr.getValue();
        }
        return null;
    }

    public static String getNodeValue(final Node node) {
        Node child;
        if (node != null) {
            if (node.hasChildNodes()) {
                child = node.getFirstChild();
                while (child != null) {
                    if (child.getNodeType() == Node.TEXT_NODE) {
                        return child.getNodeValue();
                    }
                    child = child.getNextSibling();
                }
            }
        }
        return null;
    }

    /**
     * Open XML document from Raw folder
     * 
     * @param context
     * @param xmlIdFile
     * @return
     * @throws ParserConfigurationException
     * @throws SAXException
     * @throws IOException
     */
    public static Document openDocumentFrom(final int xmlIdFile)
            throws ParserConfigurationException, SAXException, IOException,
            Resources.NotFoundException {
        final Context context = GenericApplication.getInstance()
                .getApplicationContext();
        if (xmlIdFile != ResourcesHelper.RESOURCE_NOT_FOUND) {
            final InputStream istream = context.getResources().openRawResource(
                    xmlIdFile);
            return XMLPaserUtil.buildDocument(istream);
        }
        return null;
    }

    /**
     * Open XML document from Raw folder
     * 
     * @param context
     * @param xmlIdFile
     * @return
     * @throws ParserConfigurationException
     * @throws SAXException
     * @throws IOException
     */
    public static Document openDocumentFrom(final int xmlIdFile,
            final Context context) throws ParserConfigurationException,
            SAXException, IOException, Resources.NotFoundException {
        final InputStream istream = context.getResources().openRawResource(
                xmlIdFile);
        return XMLPaserUtil.buildDocument(istream);
    }

    /**
     * Open XML document from Asset folder.
     * 
     * @param context
     * @param xmlFileName
     * @return
     * @throws ParserConfigurationException
     * @throws SAXException
     * @throws IOException
     */
    public static Document openDocumentFrom(String xmlFileName)
            throws ParserConfigurationException, SAXException, IOException {
        if (!xmlFileName.contains(".xml")) {
            xmlFileName += ".xml";
        }
        final Context context = GenericApplication.getInstance()
                .getApplicationContext();
        final InputStream istream = context.getAssets().open(xmlFileName);
        return XMLPaserUtil.buildDocument(istream);
    }

    public static boolean validateXMLSchema(final String xsdPath,
            final String xmlPath) {
        try {
            final SchemaFactory factory = SchemaFactory
                    .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
            final Schema schema = factory.newSchema(new File(xsdPath));
            final Validator validator = schema.newValidator();
            validator.validate(new StreamSource(new File(xmlPath)));
        } catch (final IOException e) {
            return false;
        } catch (final SAXException e) {
            return false;
        }
        return true;
    }
}
